import { useUserStore } from '@/store/modules/user';
import { getToken } from '@/utils/auth';
import { tansParams } from '@/utils/ruoyi';
import cache from '@/plugins/cache';
import { HttpStatus } from '@/enums/RespEnum';
import { errorCode } from '@/utils/errorCode';
import { encryptBase64, encryptWithAes, generateAesKey, decryptWithAes, decryptBase64 } from '@/utils/crypto';
import { encrypt, decrypt } from '@/utils/jsencrypt';
import globalConfig from '@/config';

/**
 * 定义接口响应
 */
export interface AxiosPromiseResponse<T = any> {
  code: number;
  msg: string;
  data: T;
}

/**
 * 定义请求配置类型
 */
export interface RequestConfig {
  url: string;
  method?: 'get' | 'post' | 'put' | 'delete' | 'options' | 'head' | 'trace' | 'connect';
  data?: any;
  params?: any;
  headers?: Record<string, any>;
  timeout?: number;
  dataType?: string;
  responseType?: string;
  sslVerify?: boolean;
  withCredentials?: boolean;
  firstIpv4?: boolean;
  success?: (res: any) => void;
  fail?: (err: any) => void;
  complete?: () => void;
}

/**
 * 定义 AxiosPromise 类型
 */
export type AxiosPromise<T = any> = Promise<AxiosPromiseResponse<T>>;

const encryptHeader = 'encrypt-key';
// 是否显示重新登录
export const isRelogin = {
  show: false,
  lastCancelTime: 0,
  isRedirecting: false  // 是否正在跳转到登录页
};

const service = {
  baseURL: globalConfig.baseUrl,
  timeout: 10000,
  header: {
    'Content-Language': 'zh_CN',
    'Content-Type': 'application/json;charset=utf-8',
    'clientid': globalConfig.clientID
  }
}

/**
 * 请求拦截器
 * @param config 
 * @returns 
 */
function requestInterceptor(config: any) {
  const isToken = config.header?.isToken === false;
  // 是否需要防止数据重复提交
  const isRepeatSubmit = config.header?.repeatSubmit === false;
  // 是否需要加密
  const isEncrypt = config.header?.isEncrypt === 'true';

  if (getToken() && !isToken) {
    config.header['Authorization'] = 'Bearer ' + getToken();
  }
  // get请求映射params参数
  if (config.method === 'get' && config.data) {
    let url = config.url + '?' + tansParams(config.data);
    url = url.slice(0, -1);
    config.data = {};
    config.url = url;
  }

  if (!isRepeatSubmit && (config.method === 'post' || config.method === 'put')) {
    const requestObj = {
      url: config.url,
      data: typeof config.data === 'object' ? JSON.stringify(config.data) : config.data,
      time: new Date().getTime()
    };
    const sessionObj = cache.local.getJSON('sessionObj');
    if (sessionObj === undefined || sessionObj === null || sessionObj === '') {
      cache.local.setJSON('sessionObj', requestObj);
    } else {
      const s_url = sessionObj.url;
      const s_data = sessionObj.data;
      const s_time = sessionObj.time;
      const interval = 500;
      if (s_data === requestObj.data && requestObj.time - s_time < interval && s_url === requestObj.url) {
        const message = '数据正在处理，请勿重复提交';
        return Promise.reject(new Error(message));
      } else {
        cache.local.setJSON('sessionObj', requestObj);
      }
    }
  }


  if (globalConfig.viteAppEncrypt === true) {

    if (isEncrypt && (config.method === 'post' || config.method === 'put')) {
      const aesKey = generateAesKey();
      config.header[encryptHeader] = encrypt(encryptBase64(aesKey));
      config.data = typeof config.data === 'object' ? encryptWithAes(JSON.stringify(config.data), aesKey) : encryptWithAes(config.data, aesKey);
    }
  }

  // FormData数据去请求头Content-Type
  // #ifdef H5
  if (config.data instanceof FormData) {
    delete config.header['Content-Type'];
  }
  // #endif

  return config;
}

/**
 * 响应拦截器
 * @param res 
 * @returns 
 */
function responseInterceptor(res: any) {
  if (globalConfig.viteAppEncrypt === true) {
    // 加密后的 AES 秘钥
    const keyStr = res.header[encryptHeader];
    // 加密
    if (keyStr != null && keyStr != '') {
      const data = res.data;
      // 请求体 AES 解密
      const base64Str = decrypt(keyStr);
      // base64 解码 得到请求头的 AES 秘钥
      const aesKey = decryptBase64(base64Str.toString());
      // aesKey 解码 data
      const decryptData = decryptWithAes(data, aesKey);
      // 将结果 (得到的是 JSON 字符串) 转为 JSON
      res.data = JSON.parse(decryptData);
    }
  }
  // 未设置状态码则默认成功状态
  const code = res.data.code || HttpStatus.SUCCESS;
  // 获取错误信息
  const msg = errorCode[code] || res.data.msg || errorCode['default'];
  // 二进制数据则直接返回
  if (res.dataType === 'arraybuffer' || res.dataType === 'text') {
    return Promise.resolve(res.data);
  }
  if (code === 401) {
    // 如果正在跳转到登录页，直接拒绝请求，不弹窗
    if (isRelogin.isRedirecting) {
      return Promise.reject('正在跳转到登录页面...');
    }

    const now = Date.now();
    // 如果用户刚刚取消过登录（5秒内），则不再弹出登录弹窗
    if (!isRelogin.show && (now - isRelogin.lastCancelTime > 5000)) {
      isRelogin.show = true;
      uni.showModal({
        title: '系统提示',
        content: '登录状态已过期，是否重新登录？',
        success: (res) => {
          if (res.confirm) {
            // 用户确认重新登录 - 设置跳转状态，阻止后续弹窗
            isRelogin.isRedirecting = true;
            useUserStore().logout().then(() => {
              uni.reLaunch({
                url: '/pages/login',
                success: () => {
                  // 页面跳转成功后重置所有状态
                  setTimeout(() => {
                    isRelogin.show = false;
                    isRelogin.isRedirecting = false;
                  }, 1000);
                },
                fail: () => {
                  // 跳转失败时重置状态
                  isRelogin.show = false;
                  isRelogin.isRedirecting = false;
                }
              });
            });
          } else {
            // 用户取消登录，记录取消时间
            isRelogin.show = false;
            isRelogin.lastCancelTime = Date.now();
          }
        },
        fail: () => {
          // 弹窗失败时也要重置状态
          isRelogin.show = false;
        }
      });
    }
    return Promise.reject('无效的会话，或者会话已过期，请重新登录。');
  } else if (code === HttpStatus.SERVER_ERROR) {
    uni.showToast({
      title: msg,
      icon: 'none',
      duration: 2000
    });
    return Promise.reject(new Error(msg));
  } else if (code === HttpStatus.WARN) {
    uni.showToast({
      title: msg,
      icon: 'none',
      duration: 2000
    });
    return Promise.reject(new Error(msg));
  } else if (code !== HttpStatus.SUCCESS) {
    uni.showToast({
      title: msg,
      icon: 'none',
      duration: 2000
    });
    return Promise.reject('error');
  } else {
    return Promise.resolve(res.data);
  }
}

/**
 * 错误处理
 * @param error 
 * @returns 
 */
function errorHandler(error: any) {
  let { message } = error;
  if (message === 'Network Error') {
    message = '后端接口连接异常';
  } else if (message.includes('timeout')) {
    message = '系统接口请求超时';
  } else if (message.includes('Request failed with status code')) {
    message = '系统接口' + message.substr(message.length - 3) + '异常';
  }
  uni.showToast({
    title: message,
    icon: 'none',
    duration: 2000
  });
  return Promise.reject(error);
}

/**
 * 请求方法
 * @param config 
 * @returns 
 */
export function request<T = any>(config: RequestConfig): AxiosPromise<T> {
  // 合并默认配置
  const finalConfig = {
    ...service,
    ...config,
    header: {
      ...service.header,
      ...config.headers
    }
  };

  // 请求拦截
  const interceptedConfig = requestInterceptor(finalConfig);

  return new Promise((resolve, reject) => {
    uni.request({
      ...interceptedConfig,
      url: service.baseURL + interceptedConfig.url,
      success: (res: any) => {
        responseInterceptor(res)
          .then(resolve)
          .catch(reject);
      },
      fail: (err: any) => {
        errorHandler(err)
          .catch(reject);
      }
    });
  });
}

// 文件下载方法
export function download(url: string, params: any, filename: string) {
  uni.showLoading({ title: '正在下载数据，请稍候' });

  const fullUrl = globalConfig.baseUrl + url;
  console.log('下载文件地址:', fullUrl);
  const queryString = params ? '?' + tansParams(params) : '';
  
  return new Promise((resolve, reject) => {
    uni.downloadFile({
      url: fullUrl + queryString,
      header: {
        'Authorization': 'Bearer ' + getToken(),
        'Clientid': globalConfig.clientID
      },
      success: (res) => {
        if (res.statusCode === 200) {
          shareFile(res.tempFilePath, filename);
          resolve(res.tempFilePath);
        } else {
          reject(new Error('下载失败'));
          uni.hideLoading();
        }
      },
      fail: (err) => {
        reject(err);
        uni.hideLoading();
      }
    });
  });
}

// 分享文件功能
function shareFile(filePath: string, filename: string) {
  uni.hideLoading();
  
  // 检查是否支持分享功能
  if (uni.shareFileMessage) {
    uni.shareFileMessage({
      filePath: filePath,
      success: () => {
        uni.showToast({
          title: '文件已分享',
          icon: 'success',
          duration: 2000
        });
      },
      fail: (err) => {
        console.log('分享失败:', err);
        // 如果分享失败，显示文件路径
        showFileInfo(filePath, filename);
      }
    });
  } else {
    // 如果不支持分享，直接显示文件信息
    showFileInfo(filePath, filename);
  }
}

// 显示文件信息
function showFileInfo(filePath: string, filename: string) {
  uni.showModal({
    title: '下载成功',
    content: `文件已下载完成\n文件名: ${filename}\n\n是否立即打开文件？`,
    confirmText: '打开文件',
    cancelText: '稍后查看',
    success: (res) => {
      if (res.confirm) {
        // 尝试打开文件
        uni.openDocument({
          filePath: filePath,
          success: () => {
            console.log('文件打开成功');
          },
          fail: (err) => {
            console.log('打开文件失败:', err);
            uni.showModal({
              title: '提示',
              content: `无法直接打开此类型文件\n文件路径: ${filePath}\n\n您可以:\n1. 在文件管理器中找到此文件\n2. 使用其他应用打开`,
              showCancel: false
            });
          }
        });
      }
    }
  });
}

// 导出 axios 实例
export default request;
